#include "parser_list.h"

using namespace krryn::parsers;

parser_parse_list::parser_parse_list() : m_IsFirstToken(true) {
	m_Root = new parser_list_node();
	m_Current = m_Root;
	m_ExpectedIndent = 0;
	m_PropertyList = false;
	m_IsRootProperty = false;
	m_ActualIndent = 0;
}

// \note this function relies on being called one time to many
// the last time should be called with tok_list_end
void parser_parse_list::handle_token(tokens_list a_Token, std::string a_Text){
	// skip the first token
	if(!m_IsFirstToken){
		delayed_token(
			m_PreviousToken, a_Token,
			m_PreviousText, a_Text
		);
	}

	m_IsFirstToken = false;
	m_PreviousToken = a_Token;
	m_PreviousText = a_Text;
}

//! Has one token to look ahead
void parser_parse_list::delayed_token(
	tokens_list a_CurrentToken, tokens_list a_NextToken, 
	std::string a_CurrentText,  std::string a_NextText){

	switch(a_CurrentToken){
		case tok_list_id:
			switch(a_NextToken){
				case tok_list_tada:
					// find the correct parent
					while(m_ExpectedIndent > m_ActualIndent){
						m_ExpectedIndent--;
						m_Current = m_Current->m_Parent;
					}
					// this is new element
					m_Current = m_Current->add_child(new parser_list_node(a_CurrentText));
					m_ExpectedIndent++;
					break;
				case tok_list_is:
					// this is a property
					m_Current->m_Properties[a_CurrentText] = new std::vector<std::string>();
					m_PropertyList = true;
					m_CurrentProperty = a_CurrentText;
					break;
				case tok_list_separator:
					// this is a property
					if(m_PropertyList){
						// this is a root property
						if(m_IsRootProperty && m_Root->m_Properties[m_CurrentProperty]){
							m_Root->m_Properties[m_CurrentProperty]->push_back(a_CurrentText);
						// this is a normal property
						}else if(m_Current->m_Properties[m_CurrentProperty]){
							m_Current->m_Properties[m_CurrentProperty]->push_back(a_CurrentText);
						}
					}
					break;
				default:
					if(m_PropertyList){
						// this is a root property
						if(m_IsRootProperty && m_Root->m_Properties[m_CurrentProperty]){
							m_Root->m_Properties[m_CurrentProperty]->push_back(a_CurrentText);
						// this is a normal property
						}else if(m_Current->m_Properties[m_CurrentProperty]){
							m_Current->m_Properties[m_CurrentProperty]->push_back(a_CurrentText);
						}

						// we've reached the end of the list
						m_PropertyList = false;
						m_IsRootProperty = false;
					}
			}
			break;
		case tok_list_root:
			m_IsRootProperty = true;
			break;
		case tok_list_newline:
			// reset the actual indent every end of line
			// because tok_list_indent is not triggered
			// if the line doesn't start with a tab char
			// so we might end up reusing the previous
			// actual indent
			m_ActualIndent = 0;
			break;
		case tok_list_indent:
			m_ActualIndent = a_CurrentText.length();
			break;
	}
}

void parser_parse_list::walk(parser_list_action *a_List){
	a_List->accept(m_Root);
	walk_recursive(a_List, m_Root);
}

void parser_parse_list::walk_recursive(parser_list_action *a_List, parser_list_node *a_Node){
	std::vector<parser_list_node*>::iterator i;
	for(i = a_Node->m_Children.begin(); i != a_Node->m_Children.end(); i++){
		a_List->accept(*i);
		walk_recursive(a_List, *i);
	}
}
